package boot.spring.controller;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.alibaba.fastjson.JSON;

import boot.spring.Application;
import boot.spring.service.LeaveService;
import boot.spring.service.SystemService;

@SpringBootTest(classes = { Application.class })
@RunWith(SpringRunner.class)
@WebAppConfiguration
public class testone {

	// 流程定义和流程静态资源 activiti的资源管理类
	@Autowired
	RepositoryService rep;
	// 运行时服务，activiti的流程运行管理类
	@Autowired
	RuntimeService runservice;

	// activiti的表单管理类
	@Autowired
	FormService formservice;

	// activiti的用户身份管理类
	@Autowired
	IdentityService identityservice;

	// activiti的任务管理类
	@Autowired
	TaskService taskservice;

	// activiti的历史管理类
	@Autowired
	HistoryService histiryservice;

	@Autowired
	private ProcessEngine processEngine;

	// 是activiti的引擎管理类
	@Autowired
	ManagementService managementService;

	@Autowired
	LeaveService leaveservice;
	@Autowired
	SystemService systemservice;

	// 发布流程
	@Ignore
	@Test
	public void testPubDefinition() {
//    	InputStream in = this.getClass().getClassLoader().getResourceAsStream("process/helloworld.zip");
//		ZipInputStream zipInputStream = new ZipInputStream(in);
		// 1 发布流程
		InputStream inputStreamBpmn = this.getClass().getResourceAsStream("/process/leave.bpmn");
		InputStream inputStreamPng = this.getClass().getResourceAsStream("/process/leave.png");
		Deployment deploy = rep.createDeployment() // 创建部署对象
				// 使用流的方式部署流程
				.addInputStream("leave.bpmn", inputStreamBpmn).addInputStream("leave.png", inputStreamPng)
				// 指定资源目录的方式部署流程
//                .addClasspathResource("process/leave.bpmn")
//				.addClasspathResource("process/leave.png")
				// 使用字符串部署流程
//				.addString("leave.bpmn", "")
				// 使用压缩包的方式部署流程
//				.addZipInputStream(zipInputStream)
				.name("xiaoyi")// 添加部署的名称
				.deploy();

		System.out.println("----getId---->" + deploy.getId());
		System.out.println("----getCategory---->" + deploy.getCategory());
		System.out.println("----getName---->" + deploy.getName());
		System.out.println("----getTenantId---->" + deploy.getTenantId());
		System.out.println("----getDeploymentTime---->" + deploy.getDeploymentTime());
		System.out.println("----getClass---->" + deploy.getClass());

		/*
		 * Map<String,Object> variables= new HashMap<String,Object>();
		 * variables.put("name","xiaoyi"); variables.put("id","001"); ProcessInstance pi
		 * =
		 * runservice.startProcessInstanceByKey("xiaoyi","xiaoyibusinessKey",variables);
		 * System.out.println("pid:" + pi.getId());
		 */
	}

	// 查看所有部署的流程
	@Ignore
	@Test
	public void testListDeployment() {
		List<Deployment> list = rep.createDeploymentQuery().list();
		System.out.println("------Deployments---->" + list.size());

	}

	// 查看流程列表
	@Ignore
	@Test
	public void testListProcess() {

		List<ProcessDefinition> list = rep.createProcessDefinitionQuery()
		/** 指定查询条件,where条件 */
//					.deploymentId(deploymentId)//使用部署对象ID查询
//					.processDefinitionId(processDefinitionId)//使用流程定义ID查询
//					.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
//					.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
				/** 排序 */
				.orderByProcessDefinitionVersion().asc()// 按照版本的升序排列
//					.orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
				.list();

//			.singleResult();//返回惟一结果集
//			.count();//返回结果集数量
//			.listPage(firstResult, maxResults);//分页查询

		System.out.println("------ProcessDefinitions---->" + list.size());

		for (ProcessDefinition item : list) {
			System.out.println("-------------》");
			System.out.println(item.getId());
			System.out.println(item.getName());
			System.out.println(item.getCategory());
			System.out.println(item.getDeploymentId());
			System.out.println(item.getDescription());
			System.out.println(item.getDiagramResourceName());
			System.out.println(item.getKey());
			System.out.println(item.getResourceName());
			System.out.println(item.getTenantId());
			System.out.println(item.getVersion());
			System.out.println(item.getClass());
			System.out.println("《-------------");
		}

	}

	// 删除流程定义
	@Ignore
	@Test
	public void deleteDeployment() {
		String deploymentId = "";
		// true 表示级联删除，即使开始流程了，也可以删除（级联删除方法将流程及相关记录全部删除）
		rep.deleteDeployment(deploymentId, true);
	}

	// 启动流程
	@Ignore
	@Test
	public void testStartTask() {
		String userid = "xiaoyi";

		// 业务标识，通常为业务表的主键，业务标识和流程实例一一对应。业务标识来源于业务系统。
		// 存储业务标识就是根据业务标识来关联查询业务系统的数据。 比如：采购流程启动一个流程实例，就可以将采购单的id作为业务标识存储到activiti中，
		// 将来查询activiti的流程实例信息就可以获取采购单的id从而关联查询业务系统数据库得到采购单信息。
		String businesskey = "001";
		String processDefinitionKey = "leave"; // 这个是在画流程图的时候定义的，用于说明要启动哪个路程

		// 这里设置的参数是对流程的控制，比如流程图上定义的assignee为${assignee} 那么对应的variables.put(“assignee”,
		// “张三”);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("name", "xiaoyi");
		variables.put("id", businesskey);
		variables.put("departid", "001");
		variables.put("leaderid", "xiaoyileader");
		ProcessInstance instance = runservice.startProcessInstanceByKey(processDefinitionKey, businesskey, variables);
		System.out.println(businesskey);
		String instanceid = instance.getId();
		System.out.println("----instanceid---->" + instanceid);
	}

	// 查询当前个人待执行的任务
	@Ignore
	@Test
	public void findPersonalTaskList1() {
		// 流程定义key
		String processDefinitionKey = "leave";
		// 任务负责人
		String assignee = "xiaoyi";
		// 创建TaskService
		TaskService taskService = processEngine.getTaskService();
		List<Task> list = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey)
				.includeProcessVariables().taskAssignee(assignee).list();
		for (Task task : list) {
			System.out.println("----------------------------");
			System.out.println("流程实例id：" + task.getProcessInstanceId());
			System.out.println("任务id：" + task.getId());
			System.out.println("任务负责人：" + task.getAssignee());
			System.out.println("任务名称：" + task.getName());

		}
	}

	// 如果要获取流程中业务的信息
	// 从task对象中得到processInstanceId
	// 根据processInstanceId获取processInstance对象
	// 从processInstance对象中获取businessKey
	// 通过businessKey获取业务的信息

	// 查询待办任务
	@Ignore
	@Test
	public void testListDepartment() {
		String userid = "xiaoyi";
		String businesskey = "001";
		String processDefinitionKey = "leave";

		// 查询所有的任务
		List<Task> list2 = taskservice.createTaskQuery().taskCandidateGroup("部门经理") // 流程图上面配置的角色
				.list();
		System.out.println("----待审批---->" + list2.size());
		for (Task item : list2) {
			System.out.println("-------------->");
			System.out.println("-------getId------>" + item.getId());
			System.out.println("-------getAssignee------>" + item.getAssignee());
			System.out.println("-------getCategory------>" + item.getCategory());
			System.out.println("-------getDescription------>" + item.getDescription());
			System.out.println("-------getExecutionId------>" + item.getExecutionId());
			System.out.println("-------getFormKey------>" + item.getFormKey());
			System.out.println("-------getName------>" + item.getName());
			System.out.println("-------getOwner------>" + item.getOwner());
			System.out.println("-------getParentTaskId------>" + item.getParentTaskId());
			System.out.println("-------getPriority------>" + item.getPriority());
			System.out.println("-------getProcessDefinitionId------>" + item.getProcessDefinitionId());
			System.out.println("-------getProcessInstanceId------>" + item.getProcessInstanceId());
			System.out.println("-------getTenantId------>" + item.getTenantId());
			System.out.println("-------getClass------>" + item.getClass());
			System.out.println("-------getCreateTime------>" + item.getCreateTime());
			System.out.println("-------getDelegationState------>" + item.getDelegationState());
			System.out.println("-------getDueDate------>" + item.getDueDate());
			System.out.println("-------getProcessVariables------>" + item.getProcessVariables());
			System.out.println("-------getTaskLocalVariables------>" + item.getTaskLocalVariables());
		}

	}

	@Ignore
	@Test
	public void completTask() {
		// 完成任务，传递任务id
		// 在完成任务前，需要校验该班里人是否具有办理该任务的权限

		String taskId = "";
		String assignee = "";
		Task singleResult = taskservice.createTaskQuery().taskId(taskId).taskAssignee(assignee).singleResult();

		if (singleResult != null) {
			taskservice.complete(taskId);
		}
	}

	// 测试清除任务
	@Ignore
	@Test
	public void testDelTask() {
		List<Task> list2 = taskservice.createTaskQuery().list();
		for (Task item : list2) {
			Map<String, Object> variables = new HashMap<String, Object>();
			variables.put("deptleaderapprove", "false");
			variables.put("reapply", "false");
			variables.put("applyuserid", "xiaoyi");
			taskservice.complete(item.getId(), variables);
			taskservice.deleteTask(item.getId());
		}

	}

	// 查询所有和我有关的流程
	@Ignore
	@Test
	public void listMy() {
		String userid = "xiaoyi";
		String businesskey = "001";
		String processDefinitionKey = "leave";

		// 查询所有的任务
		List<Task> list2 = taskservice.createTaskQuery().list();
		for (Task item : list2) {
			// 结束流程
//			Map<String,Object> variables = new HashMap<String,Object>();
//			variables.put("reapply", "false");
//			variables.put("applyuserid", "xiaoyi");
//			taskservice.complete(item.getId(),variables);

			System.out.println("-------------->");
			System.out.println("-------getId------>" + item.getId());
			System.out.println("-------getAssignee------>" + item.getAssignee());
			System.out.println("-------getCategory------>" + item.getCategory());
			System.out.println("-------getDescription------>" + item.getDescription());
			System.out.println("-------getExecutionId------>" + item.getExecutionId());
			System.out.println("-------getFormKey------>" + item.getFormKey());
			System.out.println("-------getName------>" + item.getName());
			System.out.println("-------getOwner------>" + item.getOwner());
			System.out.println("-------getParentTaskId------>" + item.getParentTaskId());
			System.out.println("-------getPriority------>" + item.getPriority());
			System.out.println("-------getProcessDefinitionId------>" + item.getProcessDefinitionId());
			System.out.println("-------getProcessInstanceId------>" + item.getProcessInstanceId());
			System.out.println("-------getTenantId------>" + item.getTenantId());
			System.out.println("-------getClass------>" + item.getClass());
			System.out.println("-------getCreateTime------>" + item.getCreateTime());
			System.out.println("-------getDelegationState------>" + item.getDelegationState());
			System.out.println("-------getDueDate------>" + item.getDueDate());
			System.out.println("-------getProcessVariables------>" + item.getProcessVariables());
			System.out.println("-------getTaskLocalVariables------>" + item.getTaskLocalVariables());

		}

	}

	// 部门经理审批通过
	@Ignore
	@Test
	public void testdepartmentAgree() {
		List<Task> list2 = taskservice.createTaskQuery().list();
		for (Task item : list2) {
			Map<String, Object> variables = new HashMap<String, Object>();
			variables.put("deptleaderapprove", "true");
			variables.put("reapply", "true");
			variables.put("applyuserid", "xiaoyi");
			taskservice.complete(item.getId(), variables);
		}

	}

	// 查询已经办理的流程
	@Ignore
	@Test
	public void queryDoneTasks() {
		List<HistoricTaskInstance> taskList = histiryservice.createHistoricTaskInstanceQuery().taskAssignee("xiaoyi")
				.finished().list();

		System.out.println("------已经办理的的流程------->");
		for (HistoricTaskInstance item : taskList) {
			System.out.println(JSON.toJSONString(item));

		}
	}

	// 办理组任务
	/*
	 * 第一步：查询组任务
	 * 
	 * 指定候选人，查询该候选人当前的待办任务。 候选人不能办理任务。
	 * 
	 * 第二步：拾取(claim)任务
	 * 
	 * 该组任务的所有候选人都能拾取。
	 * 
	 * 将候选人的组任务，变成个人任务。原来候选人就变成了该任务的负责人。
	 * 
	 * 如果拾取后不想办理该任务？
	 * 
	 * 需要将已经拾取的个人任务归还到组里边，将个人任务变成了组任务。
	 * 
	 * 第三步：查询个人任务
	 * 
	 * 查询方式同个人任务部分，根据assignee查询用户负责的个人任务。
	 * 
	 * 第四步：办理个人任务
	 * 
	 */

	// 1、根据候选人查询组任务
	@Test
	public void findGroupTaskList() {
		// 流程定义key
		String processDefinitionKey = "purchasingflow02";
		// 任务候选人
		String candidateUser = "zhangsan";
		// 创建TaskService
		TaskService taskService = processEngine.getTaskService();
		// 查询组任务
		List<Task> list = taskService.createTaskQuery()//
				.processDefinitionKey(processDefinitionKey)//
				.taskCandidateUser(candidateUser)// 根据候选人查询
				.list();

		for (Task task : list) {
			System.out.println("----------------------------");
			System.out.println("流程实例id：" + task.getProcessInstanceId());
			System.out.println("任务id：" + task.getId());
			System.out.println("任务负责人：" + task.getAssignee());
			System.out.println("任务名称：" + task.getName());

		}
	}

	// 2、用户拾取组任务
	@Test
	public void claimTask() {
		TaskService taskService = processEngine.getTaskService();
		// 要拾取的任务id
		String taskId = "6302";
		// 任务候选人id
		String userId = "lisi";
		// 拾取任务
		// 即使该用户不是候选人也能拾取(建议拾取时校验是否有资格)

		// 校验该用户有没有拾取任务的资格
		Task task = taskService.createTaskQuery()//
				.taskId(taskId).taskCandidateUser(userId)// 根据候选人查询
				.singleResult();
		if (task != null) {
			taskService.claim(taskId, userId);
			System.out.println("任务拾取成功");
		}
	}
	// 用户查询个人待办任务
	@Test
	public void findPersonalTaskList() {
	    // 流程定义key
	    String processDefinitionKey = "groupTask01";
	    // 任务负责人
	    String assignee = "zhangsan";
	    // 创建TaskService
	    TaskService taskService = processEngine.getTaskService();
	    List<Task> list = taskService.createTaskQuery()//
	            .processDefinitionKey(processDefinitionKey)//
	            .taskAssignee(assignee).list();

	    for (Task task : list) {
	        System.out.println("----------------------------");
	        System.out.println("流程实例id：" + task.getProcessInstanceId());
	        System.out.println("任务id：" + task.getId());
	        System.out.println("任务负责人：" + task.getAssignee());
	        System.out.println("任务名称：" + task.getName());

	    }
	}
	// 用户办理个人任务
	@Test 
	public void completeTask(){ //任务ID 
		String taskId = "12304"; 
		processEngine.getTaskService() .complete(taskId); 
		System.out.println("完成任务："+taskId); 
	}
	// 归还组任务
	// 如果个人不想办理该组任务，可以归还组任务，归还后该用户不再是该任务的负责人
	@Test 
	public void setAssigneeToGroupTask() { 
		// 查询任务使用TaskService 
		TaskService taskService = processEngine.getTaskService(); 
		// 当前待办任务 
		String taskId = "6004"; 
		// 任务负责人 
		String userId = "zhangsan2";

	    // 校验userId是否是taskId的负责人，如果是负责人才可以归还组任务
	    Task task = taskService.createTaskQuery().taskId(taskId)
	            .taskAssignee(userId).singleResult();
	    if (task != null) {
	        // 如果设置为null，归还组任务,该 任务没有负责人
	    	// 建议归还任务前校验该用户是否是该任务的负责人 也可以通过setAssignee方法将任务委托给其它用户负责，注意被委托的用户可以不是候选人（建议不要这样使用）
	        taskService.setAssignee(taskId, null);
	    }
	}
	// 任务交接
	@Test public void setAssigneeToCandidateUser() { 
		// 查询任务使用TaskService 
		TaskService taskService = processEngine.getTaskService(); 
		// 当前待办任务 
				String taskId = "6004"; 
				// 任务负责人 
				String userId = "zhangsan2";
	    // 校验userId是否是taskId的负责人，如果是负责人才可以归还组任务
	    Task task = taskService.createTaskQuery().taskId(taskId)
	            .taskAssignee(userId).singleResult();

	    if (task != null) {
	        // 将此任务交给其它候选人办理该 任务
	        String candidateuser = "zhangsan";
	        // 根据候选人和组任务id查询，如果有记录说明该 候选人有资格拾取该 任务
	        Task task2 = taskService.createTaskQuery().taskId(taskId)
	                .taskCandidateUser(candidateuser).singleResult();
	        if (task2 != null) {
	            // 才可以交接
	            taskService.setAssignee(taskId, candidateuser);
	        }

	    }
	}

}